<template>
  <div class="modelContainer">
    <div v-show="isBack" class="back">
      <img @click="backPrev" @mouseenter="initTimeout" @mouseleave="removeTimeout" src="@/assets/home/ico_back.png" alt="" />
    </div>
    <div v-show="isBackmore" class="backmore">
      <div @click="toPage('/homePage')" class="backbox">
        <img src="@/assets/home/ico_mars1.png" alt="" />
        <div class="backtext">基地列表</div>
      </div>
      <div @click="toPage('/basePage')" class="backbox">
        <img src="@/assets/home/ico_mars2.png" alt="" />
        <div class="backtext">基地</div>
      </div>
      <div @click="toPage('/modelPage')" class="backbox">
        <img src="@/assets/home/ico_mars3.png" alt="" />
        <div class="backtext">近景</div>
      </div>
    </div>

    <div v-show="showBase" class="popCheck">
      <div class="popCheckBox">
        <div class="checkLeft popflex">
          <div class="checkLeftBox">
            <div class="checkTitle">
              <img src="@/assets/home/ico_title.png" alt="" />
              <div>气象环境监测</div>
            </div>
            <div class="checkBox">
              <div class="checkList">
                <div class="check_name">PM2.5</div>
                <div class="check_cont">
                  <div class="check_num">19</div>
                  <div class="check_unit">ug/m³</div>
                </div>
              </div>
              <div class="checkList">
                <div class="check_name">PM 10</div>
                <div class="check_cont">
                  <div class="check_num">30</div>
                  <div class="check_unit">ug/m³</div>
                </div>
              </div>
              <div class="checkList">
                <div class="check_name">噪音</div>
                <div class="check_cont">
                  <div class="check_num">42</div>
                  <div class="check_unit">db</div>
                </div>
              </div>
              <div class="checkList">
                <div class="check_name">温度</div>
                <div class="check_cont">
                  <div class="check_num">72</div>
                  <div class="check_unit">℃</div>
                </div>
              </div>
              <div class="checkList">
                <div class="check_name">湿度</div>
                <div class="check_cont">
                  <div class="check_num">35</div>
                  <div class="check_unit">% RH</div>
                </div>
              </div>
              <div class="checkList">
                <div class="check_name">风速</div>
                <div class="check_cont">
                  <div class="check_num">15</div>
                  <div class="check_unit">m/s</div>
                </div>
              </div>
              <div class="checkList">
                <div class="check_name">风向</div>
                <div class="check_cont">
                  <div class="check_num">西南</div>
                  <div class="check_unit"></div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
  import { onMounted, ref, onBeforeUnmount } from 'vue'
  import { useRouter } from 'vue-router'
  import * as THREE from 'three';
  import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"
  import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js"

  let three = null
  let controls = null
  const router = useRouter()

  let isBack = ref(false)
  let isBackmore = ref(false)
  let showBase = ref(false)
  let timeoutId = null
  let drawInterval = null
  let jianceShow = ref(false)

  const raycaster = new THREE.Raycaster();
  const GLBLoader = new GLTFLoader();
  const dracoLoader = new DRACOLoader()
  // 设置draco路径
  dracoLoader.setDecoderPath('/draco/');
  // 使用js方式解压
  dracoLoader.setDecoderConfig({ type: "js" });
  // 初始化_initDecoder 解码器
  dracoLoader.preload();
  // 设置gltf加载器draco解码器
  GLBLoader.setDRACOLoader(dracoLoader);

  const showThreeGltf = () => {
    three = window.three
    controls = window.three.controls
    controls.enabled = true;
    controls.enablePan = true
    controls.enableRotate = true
    controls.enableZoom = true

    three.camera.position.set(0, 3, 10)
    controls.update()

    // 加载模型
    GLBLoader.load('/Mars/dancangti.glb', (gltf) => {
      gltf.scene.scale.set(0.0003, 0.0003, 0.0003)
      gltf.scene.position.set(-1, 0.5, 0)
      gltf.scene.rotation.set(0, -0.7, 0)
      _ChangeMaterialEmissive(gltf.scene)
      jianceShow.value = gltf.scene.visible
      three.scene.add(gltf.scene);
    }, undefined, (error) => {
      console.log(error);
    })
    GLBLoader.load('/Mars/jiance2.glb', (gltf) => {
      gltf.scene.scale.set(0.0006, 0.0011, 0.0011)
      gltf.scene.position.set(2, 1.5, 0)
      gltf.scene.rotation.set(0, -0.9, 0)
      _ChangeMaterialEmissive(gltf.scene)
      three.scene.add(gltf.scene);
    }, (progressEvent) => {
      const { loaded ,total ,lengthComputable } = progressEvent;
      if(lengthComputable) {
        // createCanvas()
      }
    }, (error) => {
      console.log(error);
    })

    
    // 自动旋转 整体
    controls.autoRotate = false;
    controls.autoRotateSpeed = 0.3;
    controls.addEventListener('change', () => {
      three.renderer.render(three.scene, three.camera)
    })

    // 定义点击事件
    document.addEventListener('mousemove', event => {
      // 鼠标控制对象
      const mouse = new THREE.Vector2(); 
      // 得到鼠标相对于容器的坐标
      mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
      mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
      // 执行射线检测
      raycaster.setFromCamera(mouse, three.camera);
      // 判断指定的对象中哪些被该光线照射到了，在arrGroup中筛选
      const intersects = raycaster.intersectObjects(three.scene.children)

      if (intersects.length > 0) {
        const clickObj = intersects[0]
        if(clickObj.object.name === 'ico_mark') {
          document.body.style.cursor = "pointer";
        } else {
          document.body.style.cursor = "default";
        }
      }
    })
    // 定义点击事件
    document.addEventListener('click', event => {
      // 鼠标控制对象
      const mouse = new THREE.Vector2(); 
      // 得到鼠标相对于容器的坐标
      mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
      mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
      // 执行射线检测
      raycaster.setFromCamera(mouse, three.camera);
      // 判断指定的对象中哪些被该光线照射到了，在arrGroup中筛选
      const intersects = raycaster.intersectObjects(three.scene.children)

      if (intersects.length > 0) {
        const clickObj = intersects[0]
        if(clickObj.object.name === 'ico_mark') {
          removeGltf()
          
          router.push("/detailPage")
        }
      }
    })

    animate()
  }

  const createCanvas = () => {
    if(jianceShow.value) {
      // 切换文字
      let isNext = ref(true)
      let mesh;
      // 创建canvas
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      
      // 绘制文字
      let drawCont = (value) => {
        three.scene.remove(mesh)
        ctx.clearRect(0, 0, canvas.width, canvas.height)
        ctx.font = '12px Arial';
        ctx.fillStyle = '#ff0000';
        ctx.fillText('扬尘噪声检测', 5, 24)
        if(value) {
          ctx.fillText('PM2.5: 19ug/m³', 0, 37)
          ctx.fillText('PM 10: 30ug/m³', 0, 49)
          ctx.fillText('噪音: 42db', 5, 61)
        } else {
          ctx.fillText('温度: 72℃', 5, 37)
          ctx.fillText('湿度: 35%RH', 5, 49)
          ctx.fillText('风速: 15m/s', 5, 61)
        }
        let url = canvas.toDataURL('image/png')
        let material = new THREE.MeshBasicMaterial({
          map: new THREE.TextureLoader().load(url),
          // side: THREE.DoubleSide, // 双面显示
          transparent: true,
        })
        let geometry = new THREE.PlaneGeometry(2, 2)
        mesh = new THREE.Mesh(geometry, material);
        mesh.position.set(2.59, 1, 0.4)
        mesh.rotation.set(0, -0.49, 0)
        isNext.value = !isNext.value
      }
      
      drawCont(isNext.value)
      three.scene.add(mesh)
      drawInterval = setInterval(() => {
        drawCont(isNext.value)
        three.scene.add(mesh)
      }, 3000);

      let imgico = new URL('@/assets/home/ico_mark.png', import.meta.url)
      const planeGeometry = new THREE.PlaneGeometry(0.3, 0.3);
      const planeMaterial = new THREE.MeshBasicMaterial({ 
        map: new THREE.TextureLoader().load(imgico), 
        transparent: true,
        opacity: 1,
        side: THREE.DoubleSide,
        // color: 0xffffff
      });
      const plane = new THREE.Mesh(planeGeometry, planeMaterial);
      plane.position.set(-0.3, 0.6, 0.4)
      plane.rotation.set(0, 0.3, 0)
      plane.material.cursor = 'pointer';
      plane.name = 'ico_mark'
      // 将平面添加到场景中
      three.scene.add(plane);

      showBase.value = true
      isBack.value = true
    }
  }

  const _ChangeMaterialEmissive = (parent) => {
    parent.traverse(function (obj) {
      if(obj instanceof THREE.Mesh) {
        obj.material.emissive = new THREE.Color(1,1,1);
        obj.material.emissiveIntensity = 1;
        obj.material.emissiveMap = obj.material.map;
      }
    });
  }

  const removeGltf = () => {
    if(drawInterval) {
      clearInterval(drawInterval)
    }
    cancelAnimationFrame(animate);
    three.scene.clear();
    three.renderer.content = null;
    three?.renderer.dispose()
    three?.scene.children.forEach(child => {
      three.scene.remove(child)
    })
    
    // 清理内存中的模型数据
    three?.scene.traverse((child) => {
      if (child.isMesh) {
        child.geometry.dispose();
        if(child.material) {
          const material = Array.isArray(child.material) ? child.material : [child.material];
          material.forEach(mat => mat.dispose());
        }
      }
    });
  }

  const animate = () => {
    requestAnimationFrame(animate)
    controls.update()
    three?.renderer?.render(three.scene, three.camera)
  }
  
  // 返回按钮
  const backPrev = () => {
    removeGltf()
    router.push("/basePage")
  }

  // 返回按钮 其他操作
  const initTimeout = () => {
    timeoutId = setTimeout(() => {
      isBackmore.value = true
    }, 1000)
  }

  const removeTimeout = () => {
    if (timeoutId) {
      clearTimeout(timeoutId)
      timeoutId = null
      setTimeout(() => {
        isBackmore.value = false
      }, 1500)
    }
  }

  const toPage = (page) => {
    router.push(page)
  }

  watch(jianceShow, (newVal, oldVal) => {
    if(newVal) {
      createCanvas()
    }
  }, { immediate: true, deep: true })

  onMounted(() => {
    showThreeGltf()
  })

  onBeforeUnmount(() => {
    removeGltf()
  })
</script>

<style lang="scss" scoped>
  .back {
    position: fixed;
    right: 58px;
    bottom: 36px;

    img {
      width: 115px;
      height: 110px;
      cursor: pointer;
    }
  }

  .backmore {
    position: fixed;
    right: 58px;
    bottom: 155px;

    .backbox {
      display: flex;
      flex-direction: column;
      align-items: center;
      cursor: pointer;

      .backtext {
        background-image: url("@/assets/home/img_backmore_bg.png");
        background-size: 100% 100%;
        background-position: left center;
        background-repeat: no-repeat;
        font-size: 16px;
        font-weight: bold;
        color: #effff7;
        line-height: 20px;
        padding: 9px 0 8px 42Px;
        margin-bottom: 10px;
        width: 115Px;
      }
    }
  }

  .popCheck {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 0;
    
    .popCheckBox {
      padding-top: 103px;
    }

    .checkLeft {

      .checkLeftBox {
        background-image: url('@/assets/home/img_pane_bg.png');
        background-size: 100% 100%;
        background-repeat: no-repeat;
        padding: 30px;
        margin-left: 60px;
        width: 45%;
      }
      
      .checkTitle {
        background-image: url('@/assets/home/img_title_bgc.png');
        background-size: 100% 100%;
        background-position: left center;
        background-repeat: no-repeat;
        font-size: 20px;
        font-weight: bold;
        color: #EFFFF7;
        line-height: 20px;
        padding: 10px 0 10px 14px;
        margin-bottom: 8px;
        display: flex;
        align-items: center;

        img {
          // width: 20px;
          // height: 20px;
          margin-right: 10px;
        }
      }

      .checkBox {
        display: flex;
        align-items: center;
        justify-content: space-between;
        flex-wrap: wrap;

        .checkList {
          width: 44%;
          display: flex;
          align-items: center;
          background-image: url('@/assets/home/img_sub_bg.png');
          background-size: 100% 100%;
          background-repeat: no-repeat;
          margin-top: 20px;
          display: flex;
          align-items: center;
          justify-content: space-between;
          padding: 10px;

          .check_name {
            font-weight: bold;
            font-size: 14px;
            color: #FFFFFF;
            line-height: 20px;
          }

          .check_cont {
            display: flex;
            align-items: center;

            .check_num {
              font-weight: bold;
              font-size: 20px;
              color: #D5E2E8;
              line-height: 29px;
            }

            .check_unit {
              font-weight: 400;
              font-size: 14px;
              color: #999999;
              line-height: 20px;
              padding-left: 7px;
            }
          }
        }
      }
    }
  }
</style>
